﻿Public Class Form1

    Public Const Height1 As Integer = 300
    Public Const Height2 As Integer = 345

    Public Enum ESyncOption
        Upload = 1
        Download = 2
        Exchange = 3
        'MirrorLocal = 4
        'MirrorRemote = 5
    End Enum

#Region "Event Handlers - Form"
    Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
        If My.Application.CommandLineArgs.Count > 0 Then PerformUpgrade()

        Me.Height = Height1

        'Set values from last time
        ctrlFolderLocal.SelectedFolder = My.Settings.LocalFolder
        ctrlFolderRemote.SelectedFolder = My.Settings.RemoteFolder
        ctrlAwsKey.Value = My.Settings.AwsKeyId
        ctrlAwsSecret.Value = My.Settings.AwsKeySecret
        If My.Settings.UseAmazon Then radAmazon.Checked = True
        radDownload.Enabled = True
        Select Case CType(My.Settings.SyncOption, ESyncOption)
            Case ESyncOption.Download : radDownload.Checked = True
            Case ESyncOption.Upload : radUpload.Checked = True
            Case ESyncOption.Exchange : radExchange.Checked = True
        End Select

        'Load, Show/Hide as appropriate
        rad_CheckedChanged(Nothing, Nothing)
        ctrlAws_Changed(Nothing)
        ctrlBucket.SelectedValue = My.Settings.AwsBucketName

        'Events to be hooked up after load/set-values
        AddHandler radAmazon.CheckedChanged, AddressOf rad_CheckedChanged
        AddHandler radFolder.CheckedChanged, AddressOf rad_CheckedChanged
        AddHandler ctrlFolderLocal.Changed, AddressOf ctrlFolderLocal_Changed
        AddHandler ctrlFolderRemote.Changed, AddressOf ctrlFolderRemote_Changed
        AddHandler ctrlAwsKey.Changed, AddressOf ctrlAws_Changed
        AddHandler ctrlAwsSecret.Changed, AddressOf ctrlAws_Changed


        'Lock down anything from the Config file
        If CConfig.AwsKeyId.Length > 0 Then
            My.Settings.AwsKeyId = CConfig.AwsKeyId
            ctrlAwsKey.Enabled = False
            ctrlAwsKey.HideValue()
            radAmazon.Checked = True
            radFolder.Enabled = False
            radAmazon.Enabled = False
        End If
        If CConfig.AwsKeySecret.Length > 0 Then
            My.Settings.AwsKeySecret = CConfig.AwsKeySecret
            ctrlAwsSecret.Enabled = False
            ctrlAwsSecret.HideValue()
        End If
        If CConfig.AwsBucketName.Length > 0 Then
            My.Settings.AwsBucketName = CConfig.AwsBucketName
            ctrlBucket.Enabled = False
            ctrlBucket.SelectedText = CConfig.AwsBucketName
        End If
        If CConfig.LocalFolder.Length > 0 Then
            My.Settings.LocalFolder = CConfig.LocalFolder
            ctrlFolderLocal.Enabled = False
        End If
        If CConfig.RemoteFolder.Length > 0 Then
            My.Settings.RemoteFolder = CConfig.RemoteFolder
            ctrlFolderRemote.Enabled = False
            radFolder.Checked = True
            radFolder.Enabled = False
            radAmazon.Enabled = False
        End If
        If CConfig.SyncOption > 0 Then
            Select Case CType(CConfig.SyncOption, ESyncOption)
                Case ESyncOption.Download : radDownload.Checked = True
                Case ESyncOption.Upload : radUpload.Checked = True
                Case ESyncOption.Exchange : radExchange.Checked = True
            End Select
            radUpload.Enabled = False
            radDownload.Enabled = False
            radExchange.Enabled = False
        End If
    End Sub
#End Region

#Region "Event Handers - Controls"
    'Folders
    Private Sub ctrlFolderLocal_Changed()
        My.Settings.LocalFolder = ctrlFolderLocal.SelectedFolder
    End Sub
    Private Sub ctrlFolderRemote_Changed()
        My.Settings.RemoteFolder = ctrlFolderRemote.SelectedFolder
    End Sub

    'Radio Buttons
    Private Sub rad_CheckedChanged(sender As System.Object, e As System.EventArgs)
        ctrlFolderRemote.Visible = radFolder.Checked
        ctrlAwsKey.Visible = radAmazon.Checked
        ctrlAwsSecret.Visible = radAmazon.Checked
        ctrlBucket.Visible = radAmazon.Checked
        If radAmazon.Checked Then Me.Height = Height2 Else Me.Height = Height1

        If Not IsNothing(sender) Then My.Settings.UseAmazon = radAmazon.Checked
    End Sub
    Private Sub rad2Way_CheckedChanged(sender As System.Object, e As System.EventArgs) Handles radDownload.CheckedChanged, radUpload.CheckedChanged, radExchange.CheckedChanged
        If Not radDownload.Enabled Then Exit Sub 'Suppress event firing during init

        If radDownload.Checked Then
            My.Settings.SyncOption = ESyncOption.Download
        ElseIf radUpload.Checked Then
            My.Settings.SyncOption = ESyncOption.Upload
        Else
            My.Settings.SyncOption = ESyncOption.Exchange
        End If
    End Sub

    'Textbox/Dropdown
    Private Sub ctrlAws_Changed(sender As Object)
        My.Settings.AwsKeyId = ctrlAwsKey.Value
        My.Settings.AwsKeySecret = ctrlAwsSecret.Value

        ctrlBucket.Enabled = ctrlAwsKey.Value.Length > 0 AndAlso ctrlAwsSecret.Value.Length > 0
        If ctrlBucket.Enabled Then
            Try
                ctrlBucket.Enabled = False
                With New CSourceS3(ctrlAwsKey.Value, ctrlAwsSecret.Value)
                    Dim names As List(Of String) = .Buckets
                    ctrlBucket.Values = names
                    If IsNothing(sender) AndAlso names.Count > 0 Then ctrlBucket.SelectedValue = names(0) Else ctrlBucket.SelectedText = String.Empty
                End With
                ctrlBucket.Enabled = True
            Catch ex As Exception
                ctrlBucket.SelectedText = ex.Message
                ctrlBucket.Enabled = False
            End Try
        End If
    End Sub
    Private Sub ctrlBucket_Changed() Handles ctrlBucket.Changed
        My.Settings.AwsBucketName = ctrlBucket.SelectedValue
    End Sub

    'Menus
    Private Sub SignUpForAmazonCloudServicesToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles SignUpForAmazonCloudServicesToolStripMenuItem.Click
        Process.Start("https://aws-portal.amazon.com/gp/aws/developer/registration/index.html")
    End Sub
    Private Sub DonateToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles DonateToolStripMenuItem.Click
        Process.Start("https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KQ87BW6ZCTBVA")
    End Sub
    Private Sub CheckForUpdatedVersionToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles CheckForUpdatedVersionToolStripMenuItem.Click
        Try
            CheckForUpgrade()
        Catch ex As Exception
            MsgBox(ex.Message, MsgBoxStyle.OkOnly, "Failed to Check for new Version")
        End Try
    End Sub

    'Buttons
    Private Sub ctrlBucket_CreateClick(name As String) Handles ctrlBucket.CreateClick
        Try
            With New CSourceS3(ctrlAwsKey.Value, ctrlAwsSecret.Value)
                .CreateBucket(name)
                ctrlBucket.Values = .Buckets
                ctrlBucket.SelectedValue = name
            End With
        Catch ex As Exception
            ctrlBucket.SelectedText = ex.Message
            ctrlBucket.Enabled = False
        End Try
    End Sub
    Private Sub btnSync_Click(sender As System.Object, e As System.EventArgs) Handles btnSync.Click
        Dim source As CSourceAbstract = New CSourceFolder(ctrlFolderLocal.SelectedFolder)

        If String.IsNullOrEmpty(ctrlFolderLocal.SelectedFolder) Then
            MsgBox("A local folder must be selected", MsgBoxStyle.OkOnly, "Required Field")
            Exit Sub
        End If
        btnSync.Enabled = False

        My.Settings.AwsBucketName = ctrlBucket.SelectedValue

        Dim target As CSourceAbstract = Nothing
        If My.Settings.UseAmazon Then
            target = New CSourceS3(My.Settings.AwsKeyId, My.Settings.AwsKeySecret, My.Settings.AwsBucketName)
        Else
            target = New CSourceFolder(ctrlFolderRemote.SelectedFolder)
        End If

        Dim sync As ESync = ESync.OneWay_Inserts
        Select Case CType(My.Settings.SyncOption, ESyncOption)
            Case ESyncOption.Download
                Dim temp As CSourceAbstract = source
                source = target
                target = temp
            Case ESyncOption.Exchange
                sync = ESync.TwoWay_Inserts
        End Select


        AddHandler source.Notify, AddressOf Notify
        AddHandler source.CopyFinish, AddressOf CopyFinish
        AddHandler source.CopyFailed, AddressOf CopyFailed
        If TypeOf target Is CSourceS3 Then
            AddHandler source.CopyStart, AddressOf CopyStart
        End If

        AddHandler target.Notify, AddressOf Notify
        If TypeOf source Is CSourceS3 Then
            AddHandler target.CopyStart, AddressOf CopyStart
        End If
        AddHandler target.CopyFinish, AddressOf CopyFinish
        AddHandler target.CopyFailed, AddressOf CopyFailed

        ListBox1.Items.Clear()

        With New DSync(AddressOf CSync.SyncFiles)
            .BeginInvoke(source, target, sync, AddressOf SyncComplete, Nothing)
        End With
        'CSync.SyncFiles(source, target, sync)
    End Sub
#End Region

#Region "Threading"
    Private Delegate Sub DNotify(msg As String)
    Private Delegate Sub DSync(source As CSourceAbstract, target As CSourceAbstract, sync As ESync)
    Private Sub Notify(msg As String)
        If ListBox1.InvokeRequired Then
            ListBox1.Invoke(New DNotify(AddressOf Notify), New Object() {msg})
        Else
            If ListBox1.Items.Count > 5000 Then ListBox1.Items.Clear()
            ListBox1.Items.Add(msg)
            ListBox1.Refresh()
            ListBox1.SelectedIndex = ListBox1.Items.Count - 1

            If msg = "Sync Complete" Then btnSync.Enabled = True
        End If
    End Sub
    Private Sub SyncComplete(ar As IAsyncResult)
        Notify("Sync Complete")
        'btnSync.Enabled = True
    End Sub
#End Region

#Region "Logging"
    Private Sub CopyStart(key As String, fileNumber As Integer, totalFiles As Integer, fileSize As Long)
        Notify(String.Concat(" #", fileNumber.ToString("n0"), " of ", totalFiles.ToString("n0"), ":", vbTab, key, " ...", vbTab, "(", CUtilities.FileSize(fileSize), ")"))
    End Sub
    Private Sub CopyFinish(key As String, copiedBytes As Long, totalBytes As Long, startDate As DateTime)
        Dim percent As Double = (100.0 * copiedBytes / totalBytes)
        Dim eta As DateTime = DateTime.Now
        If percent > 0 Then eta = startDate.AddTicks(DateTime.Now.Subtract(startDate).Ticks * 100.0 / percent)
        Notify(String.Concat(vbTab, percent.ToString("n4"), "%", vbTab, CUtilities.Timespan(eta, "", " remaining"), vbTab, "(", CUtilities.FileSize(copiedBytes), " of ", CUtilities.FileSize(totalBytes), ")"))
    End Sub
    Private Sub CopyFailed(key As String, ex As Exception)
        Notify(String.Concat(" FAILED: ", key, vbTab, ex.Message))
    End Sub
#End Region

#Region "Upgrading"
    Private Shared NORMAL_PATH As String = My.Application.Info.DirectoryPath & "\FileSync.exe"
    Private Shared UPGRADE_PATH As String = My.Application.Info.DirectoryPath & "\FileSync.upgrade.exe"
    Private Sub CheckForUpgrade()
        Dim myVersion As String = My.Application.Info.Version.ToString
        Dim wc As New Net.WebClient()
        Dim newVersion As String = wc.DownloadString("http://s3.amazonaws.com/Picasso.FileSync/version.txt")
        If myVersion = newVersion Then
            MsgBox("Application is up to date", MsgBoxStyle.OkOnly, "No Upgrade available")
            Exit Sub
        End If
        If IO.File.Exists(UPGRADE_PATH) Then IO.File.Delete(UPGRADE_PATH)
        wc.DownloadFile("http://s3.amazonaws.com/Picasso.FileSync/FileSync.exe", UPGRADE_PATH)
        Process.Start(UPGRADE_PATH, "upgrade")
        Me.Close()
        Application.Exit()
    End Sub
    Private Sub PerformUpgrade()
        Threading.Thread.Sleep(500)
        Try
            IO.File.Delete(NORMAL_PATH)
            IO.File.Copy(UPGRADE_PATH, NORMAL_PATH)
            Process.Start(NORMAL_PATH)
            Me.Close()
        Catch ex As Exception
            PerformUpgrade()
        End Try
    End Sub
#End Region

End Class
